package top.yongyan0624.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import top.yongyan0624.entity.SysMenu;
import top.yongyan0624.entity.SysRole;
import top.yongyan0624.entity.SysUser;
import top.yongyan0624.mapper.SysUserMapper;
import top.yongyan0624.service.SysMenuService;
import top.yongyan0624.service.SysRoleService;
import top.yongyan0624.service.SysUserService;
import top.yongyan0624.utils.RedisUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author yongyan
 * @since 2021-08-15
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {
    @Autowired
    private SysRoleService sysRoleService;

    @Autowired
    private SysMenuService sysMenuService;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private RedisUtils redisUtils;

    @Override
    public SysUser getByUsername(String username) {
        return getOne(new QueryWrapper<SysUser>().eq("username",username));
    }

    @Override
    public String getUserAuthorityInfo(Long userId) {
        //获取角色（ROLE_admin）和菜单操作权限（sys:user:list）
        String authority = "";

        //这里做一下权限信息的缓存
        if (redisUtils.hasKey("grantedAuthority:" + userId)) {
            //说明已经存在权限信息的缓存，直接赋值即可
            authority = (String) redisUtils.get("grantedAuthority:" + userId);
        } else {
            //没有查询到缓存，开始获取用户的权限信息的缓存

            //获取角色编码(ROLE_admin,ROLE_normal,)
            List<SysRole> roles = sysRoleService.list(new QueryWrapper<SysRole>()
                    .inSql("id", "select role_id from sys_user_role where user_id = " + userId));

            if (roles.size() > 0) {
                //通过流 映射roles中的所有role中的Code，加上前缀后 用 , 号缝合起来
                String roleCodes = roles.stream().map(role -> "ROLE_" + role.getCode()).collect(Collectors.joining(","));

                authority = roleCodes.concat(",");
            }

            //获取菜单操作编码(sys:user:list...)
            //比较麻烦的是需要通过userId获取roleId，再通过roleId获取对应的menuId，通过menuId最后获取菜单操作编码（perms）
            List<Long> menuIds = sysUserMapper.getNavMenuIds(userId);

            if (menuIds.size() > 0) {

                List<SysMenu> menus = sysMenuService.listByIds(menuIds);
                String menuPerms = menus.stream().map(menu -> menu.getPerms()).collect(Collectors.joining(","));

                authority = authority.concat(menuPerms);
            }

            //将信息缓存到redis，前缀:userId 作为key，value就是权限字符串，缓存时间为十二个小时
            redisUtils.set("grantedAuthority:" + userId, authority, 12 * 60 * 60);
        }

        return authority;
    }


    @Override
    public void clearUserAuthorityInfo(Long userId) {
        redisUtils.del("grantedAuthority:" + userId);
    }

    @Override
    public void clearUserAuthorityInfoByRoleId(Long roleId) {
        List<SysUser> sysUsers = this.list(new QueryWrapper<SysUser>()
                .inSql("id", "select user_id from sys_user_role where role_id = " + roleId));

        sysUsers.forEach(u -> {
            this.clearUserAuthorityInfo(u.getId());
        });
    }

    @Override
    public void clearUserAuthorityInfoByMenuId(Long menuId) {
        List<SysUser> sysUsers = sysUserMapper.listByMenuId(menuId);

        sysUsers.forEach(u -> {
            this.clearUserAuthorityInfo(u.getId());
        });
    }

}
